package fmppc.druid;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import fmppc.config.properties.MyBatisPlusPropertiesConfigBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Servlet;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 类描述: 阿里-德鲁伊连接池配置
 *
 * @author : 王雷
 * @date : 2022/4/8 0008 下午 8:49
 */
@Configuration
@EnableConfigurationProperties(value = MyBatisPlusPropertiesConfigBean.class)
public class DataSourceDruidConfig {

    /**
     * 属性描述：MyBatis配置属性
     * @date : 2022/9/17 0017 下午 2:09
     */
    private final MyBatisPlusPropertiesConfigBean myBatisPlusPropertiesConfigBean;

    /**
     * 功能描述：阿里-德鲁伊连接池配置
     * @date : 2022/9/17 0017 下午 2:14
     */
    public DataSourceDruidConfig(MyBatisPlusPropertiesConfigBean myBatisPlusPropertiesConfigBean) {
        this.myBatisPlusPropertiesConfigBean = myBatisPlusPropertiesConfigBean;
    }

    /**
     * 功能描述：数据源加载
     * <br/>
     * 将自定义的Druid数据源添加到容器中，不在让springboot自动创建
     * 绑定全局配置文件中的druid数据源属性到com.alibaba.druid.pool.DruidDataSource从而让他们生效
     *
     * @ConfigurationProperties(prefix = "spring.datasource")作用就是将全局配置文件中
     * 前缀为springdatasource的属性值注入到com.alibaba.druid.pool.DruidDataSource的同名参数中
     * @date : 2022/4/8 0008 下午 9:12
     */
    @Bean
//    @Bean(destroyMethod = "close", initMethod = "init")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
        final DruidDataSource build = DataSourceBuilder.create().type(DruidDataSource.class).build();
        //初始化物理连接的数量
        build.setInitialSize(5);
        try {
            //stat是sql监控，wall是防火墙(如果不添加则监控无效)，不能添加log4j不然会出错
            build.addFilters("stat,wall,log4j");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return build;
//        return new DruidDataSource();
    }

    /**
     * 功能描述：配置Druid监控管理后台的servlet
     * <br />
     * 内置Servlet容器时没有web.xml文件，所以使用springboot的注册servlet的方式
     *
     * @date : 2022/4/8 0008 下午 9:17
     */
    @Bean
    public ServletRegistrationBean<? extends Servlet> statViewServlet() {
//        ServletRegistrationBean<? extends Servlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
        final MyBatisPlusPropertiesConfigBean.DruidConfig druidConfig = myBatisPlusPropertiesConfigBean.getDruidConfig();
        ServletRegistrationBean<? extends Servlet> bean = new ServletRegistrationBean<>(new StatViewServlet()
                , druidConfig.getUrlMapping());
        //这些参数可以在com.alibaba.druid.support.http.StatViewServlet的父类com.alibaba.druid.support.http.ResourceServlet 中找到
        Map<String, String> initParams = new HashMap<>(16);
        //后台管理界面的登录账号
        initParams.put("loginUsername", druidConfig.getLoginUsername());
        //后台管理界面的登录密码
        initParams.put("loginPassword", druidConfig.getLoginPassword());
        //后台允许谁可以访问
        //initParams.put("allow","localhost");//表示只有本机可以访问
        /*
         * 后台允许谁可以访问
         * initParams.put("allow","localhost");//表示只有本机可以访问
         * 为空或者为null时，表示允许所有访问
         * */
        initParams.put("allow", druidConfig.getAccessPermission());
        /*
         * Druid后台拒绝访问谁——黑名单
         * 下面表示禁止此ip访问
         * */
        initParams.put("dz", "192.168.1.20");
        //设置初始化参数
        bean.setInitParameters(initParams);
        return bean;
    }

    /**
     * 功能描述：用于配置web和Druid数据源之间的管理关联监控统计
     *
     * @date : 2022/4/8 0008 下午 9:21
     */
    @Bean
    public FilterRegistrationBean<WebStatFilter> webStatFilter() {
        FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new WebStatFilter());
        //exclusions:设置哪些请求进行过滤排除掉，从而不进行统计
        Map<String, String> initParams = new HashMap<>(16);
        initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
        bean.setInitParameters(initParams);
        //"/*" 表示过滤所有请求
        bean.setUrlPatterns(Collections.singletonList("/*"));
        return bean;
    }
}
